package org.dragonnova.meetingclient.core.manager;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.util.Log;

import org.dragonnova.meetingclient.client.service.WIFIService;
import org.dragonnova.meetingclient.core.message.GroupMessage;
import org.dragonnova.meetingclient.core.message.Message;
import org.dragonnova.meetingclient.core.message.MessageBuilder;
import org.dragonnova.meetingclient.core.net.SocketUtils;
import org.dragonnova.meetingclient.core.net.netty.MsgDecoder;
import org.dragonnova.meetingclient.core.net.netty.MsgEncoder;
import org.dragonnova.meetingclient.core.net.netty.NettyClient;
import org.dragonnova.meetingclient.model.bean.DeviceInfo;
import org.dragonnova.meetingclient.model.bean.VoiceInfo;
import org.dragonnova.meetingclient.utils.LogUtil;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * Created by hucn on 2016/6/13.
 * Description:
 */
public class NettyManager implements NetManager {

    private static final String TAG = NettyManager.class.getName();

    // TCP通信端口
    private final static int SERVER_NETTY_PORT = 2347;
    // UDP多播地址
    private final static String MULTICAST_NETWORK_IP = "239.255.255.250";
    // 多播端口
    private final static int MULTICAST_NETWORK_PORT = 25221;
    // mContext
    private Context mContext;
    // wifiManager
    private WifiManager mWifiManager;
    // 处理数据
    private NettyClientHandler nettyClientHandler = new NettyClientHandler();
    // NettyClient
    private NettyClient nettyClient;

    /**
     * 传递的数据内容
     */
    private static final int KEY_ACTION_GROUP_NO_JOIN = 0xBB;
    private static final int KEY_ACTION_GROUP_ALLOW_JOIN = 0xAA;
    private static final int KEY_ACTION_GROUP_JOINED = 0xDD;
    private static final byte KEY_ACTION_GROUP_CONFIRM_1 = (byte) 0xEE;
    private static final byte KEY_ACTION_GROUP_JOIN_REQUEST = (byte) 0xCC;
    private static final byte KEY_ACTION_GROUP_CONFIRM_2 = (byte) 0xFF;
    private static final int KEY_ACTION_TRANSFER_VOICE_DATA = 0x10;
    private static final byte KEY_ACTION_GROUP_EXIT = (byte) 0x99;
    private static final int KEY_ACTION_GROUP_CONNECTED_REQUEST = 0x01;
    private static final int KEY_ACTION_GROUP_CONNECTED_RESPONSE = 0x02;
    private static final int KEY_ACTION_VOICE_REQUEST_START = 0x03;
    private static final int KEY_ACTION_VOICE_REQUEST_STOP = 0x04;
    private static final int KEY_ACTION_VOICE_REQUEST_PERSIST = 0x08;
    private static final int KEY_ACTION_VOICE_RESPONSE_PERMIT = 0x05;
    private static final int KEY_ACTION_VOICE_RESPONSE_PREVENT = 0x06;
    private static final int KEY_ACTION_VOICE_RESPONSE_FINISH = 0x07;
    private static final int KEY_ACTION_VOICE_RESPONSE_PERSIST = 0x09;
    private static final int KEY_ACTION_GROUP_CHANGE_LANGUAGE = 0x31;
    private static final int KEY_ACTION_GROUP_CHANGE_LANGUAGE_COMPLETE = 0x32;
    private static final int KEY_ACTION_DEVICE_REQUEST = 0x35;
    private static final int KEY_ACTION_DEVICE_RESPONSE = 0x36;
    private static final int KEY_ACTION_DEVICE_CHANGE_REQUEST = 0x37;
    private static final int KEY_ACTION_DEVICE_CHANGE_RESPONSE_SUCCESS = 0x38;

    public NettyManager(Context context, WifiManager wifiManager) {
        mContext = context;
        mWifiManager = wifiManager;
    }

    @Override
    public void start() {
        startNetty();
    }

    @Override
    public void stop() {

    }

    @Override
    public void enbleNetWorker() {

    }

    @Override
    public void disableNetWorker() {

    }

    @Override
    public void tryGroup() {

    }

    @Override
    public void tryDisGroup() {

    }

    @Override
    public void sendVoiceMessage(VoiceInfo voiceInfo) {

    }

    @Override
    public void changeServerLanguage(char language) {

    }

    @Override
    public void requestVoiceStart() {

    }

    @Override
    public void requestVoiceStop() {

    }

    @Override
    public boolean isStarted() {
        return false;
    }

    @Override
    public void requestVoicePersist() {

    }

    private void startNetty() {
    }

    private Message getBeatMsg() {
        byte[] packageData = getDeviceInfoPacket();
        return new MessageBuilder(new GroupMessage()).setData(packageData).setDataLength(packageData.length).setAction(new byte[]{KEY_ACTION_GROUP_CONNECTED_REQUEST}).create();
    }


    /**
     * 获取deviceinfo的byte[]
     */
    private byte[] getDeviceInfoPacket() {
        String ipAddr = SocketUtils.convertIntIpAddress(mWifiManager.getConnectionInfo().getIpAddress());
        String wifiMacAddr = mWifiManager.getConnectionInfo().getMacAddress();
        //String hostId, String hostName, String wifiMacAddr, String btMacAddr, String wifiAddr, String btName, char language, int port
        return new DeviceInfo(WIFIService.mLocalDeviceInfo.getHostId(), WIFIService.mLocalDeviceInfo.getHostName(), wifiMacAddr, WIFIService.mLocalDeviceInfo.getBtMacAddr(), ipAddr, WIFIService.mLocalDeviceInfo.getBtName(), WIFIService.mLocalDeviceInfo.getLanguage(), WIFIService.mLocalDeviceInfo.getPort()).encode();
    }

    /**
     * 网络事件处理器
     */
    @ChannelHandler.Sharable
    private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            Log.i(TAG, "SocketChannel.id=" + ch.id());
            ch.pipeline().addLast("decoder", new MsgDecoder());
            ch.pipeline().addLast("encoder", new MsgEncoder());
            ch.pipeline().addLast(new NettyClientHandler());
        }
    }

    @ChannelHandler.Sharable
    public class NettyClientHandler extends ChannelHandlerAdapter {
        private String TAG = NettyClientHandler.class.getName();
        private Channel mChannel;

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            if (ctx != null) {
                mChannel = ctx.channel();
                Log.i(TAG, "客户端active");
            }
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg)
                throws Exception {

            Message serverMsg = (Message) msg;
            if (msg != null) {
                int action = SocketUtils.byte2Int(serverMsg.getAction());
                switch (action) {
                    case KEY_ACTION_TRANSFER_VOICE_DATA:
                        String voiceDataString = new String(serverMsg.getPacketData());
                        LogUtil.iii("from " + ctx.channel().remoteAddress() + ",the msg is:" + voiceDataString);
                        break;
                    case KEY_ACTION_GROUP_CONNECTED_RESPONSE:
                        LogUtil.iii("from " + ctx.channel().remoteAddress() + ",connetion is on the way");
                        break;
                    case KEY_ACTION_VOICE_RESPONSE_PERMIT:
                    case KEY_ACTION_VOICE_RESPONSE_PERSIST:
                    case KEY_ACTION_VOICE_RESPONSE_FINISH:
                    case KEY_ACTION_VOICE_RESPONSE_PREVENT:
                        break;
                    default:
                        LogUtil.iii("from " + ctx.channel().remoteAddress() + ", message is " + serverMsg.getPacketData().toString());
                        break;
                }
            }
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
            Log.i(TAG, "客户端收到服务器响应数据处理完成");
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
                throws Exception {
            Log.i(TAG, "Unexpected exception from downstream:" + cause.getMessage());
            Log.i(TAG, "客户端异常退出");
            ctx.close();
        }

        public void sendData(Message netGroupMsg) {
            if (mChannel != null) {
                mChannel.writeAndFlush(netGroupMsg);
            } else {
                Log.i(TAG, "===mContextSocket==null=====");
            }
        }

        @Override
        public void userEventTriggered(ChannelHandlerContext ctx, Object msg) throws Exception {
            super.userEventTriggered(ctx, msg);
            if (msg instanceof IdleStateEvent) {
                IdleStateEvent e = (IdleStateEvent) msg;
                switch (e.state()) {
                    case WRITER_IDLE:
                        mChannel.close();  //call back channelInactive(ChannelHandlerContext ctx)
                        LogUtil.eee(mChannel.remoteAddress() + "---No data was received for a while ,read time out... ...");
                        break;
                    case READER_IDLE:
                        mChannel.close();
                        LogUtil.eee(mChannel.remoteAddress() + "---No data was sent for a while.write time out... ...");
                        break;
                    case ALL_IDLE:
                        LogUtil.eee(mChannel.remoteAddress() + "---send beat message to the server... ...");
                        // 发送心跳
                        ctx.channel().writeAndFlush(getBeatMsg());
                    default:
                        break;
                }
            }
        }
    }
}
